package com.woniu.gateway.filter;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.common.ResponseData;
import com.woniu.common.ResponseEnum;
import com.woniu.common.dto.AuthDTO;
import com.woniu.common.dto.RoleAuthDTO;
import com.woniu.common.dto.UserDTO;
import com.woniu.common.dto.WhiteDTO;
import com.woniu.common.utils.UserUtil;

import com.woniu.gateway.feign.WhiteFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
@Order(10)
public class AuthFilter implements GlobalFilter {
    @Autowired
    private ReactiveStringRedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //前提是登录：会把用户的权限（资源:path）放到redis,用hash（key：userId,value:path）

        //鉴权:拿用户id,path

        ServerHttpRequest request = exchange.getRequest();

        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        String path = request.getPath().toString();

        //白名单
        if (path.contains("/user/getCode")){
            return chain.filter(exchange);
        }
        if (path.contains("/face/faceDelete")){
            return chain.filter(exchange);
        }
        if (checkWhite(path)){
            return chain.filter(exchange);
        }


        String token = exchange.getRequest().getHeaders().getFirst("token");
        Object id = stringRedisTemplate.opsForHash().get("User", token);

        if (checkAuth(id.toString(), path)) {
            return chain.filter(exchange);
        }

        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(new ResponseData<>().fail(ResponseEnum.NO_AUTH));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        response.setStatusCode(HttpStatus.FORBIDDEN);
        return response.writeWith(Mono.just(buffer));

    }

    private boolean checkAuth(String id, String path) {
        //第一步，先在缓存内查询当前用户的角色id
        Object userRole = stringRedisTemplate.opsForHash().get("UserRole", "账户ID--" + id.toString());
        if (userRole == null) {
            //直接无权限
            return false;
        }
        userRole = JSON.parseObject(userRole.toString(), Integer.class);
        List<Object> roleAuth = stringRedisTemplate.opsForHash().values("RoleAuth");
        ArrayList<RoleAuthDTO> roleAuthDTOList = new ArrayList<>();
        for (Object o : roleAuth) {
            RoleAuthDTO roleAuthDTO = JSON.parseObject(o.toString(), RoleAuthDTO.class);
            roleAuthDTOList.add(roleAuthDTO);
        }

        Object finalUserRole = userRole;
        List<RoleAuthDTO> collect = roleAuthDTOList.stream().filter(e -> e.getRoleId().equals(finalUserRole)).collect(Collectors.toList());
        //通过collect 拿到当前角色的权限
        List<Object> auth = stringRedisTemplate.opsForHash().values("Auth");
        Iterator<Object> iterator1 = auth.iterator();
        ArrayList<AuthDTO> authDTOList = new ArrayList<>();
        while (iterator1.hasNext()) {
            Object next = iterator1.next();
            AuthDTO authDTO = JSON.parseObject(next.toString(), AuthDTO.class);
            authDTOList.add(authDTO);
        }
        for (RoleAuthDTO roleAuthDTO : collect) {
            for (AuthDTO authDTO : authDTOList) {
                if (roleAuthDTO.getAuthid().equals(authDTO.getId())) {
                    if (authDTO.getAuthcode().equals(path)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }


    private boolean checkWhite(String path) {
        Set<Object> whiteList = stringRedisTemplate.opsForHash().keys("WhiteList");
        for (Object white : whiteList) {
            if (path.equals(white)) {
                return true;
            }
        }
        return false;
    }

}
